﻿// 0731train02.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <limits.h>

using namespace std;

/*
 给你一个整数 x ，如果 x 是一个回文整数，返回 true ；否则，返回 false 。
回文数是指正序（从左向右）和倒序（从右向左）读都是一样的整数。
- 例如，121 是回文，而 123 不是。
示例 1：
输入：x = 121
输出：true
示例 2：
输入：x = -121
输出：false
解释：从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
示例 3：
输入：x = 10
输出：false
解释：从右向左读, 为 01 。因此它不是一个回文数。
 */

void solve01(int num)
{
    string oh_str = to_string(num);

    int left = 0;
    int right = oh_str.size() - 1;

    bool result = true;
    while (left<=right)
    {
        if (oh_str[left]==oh_str[right])
        {
            left++;
            right--;
        }
        else
        {
            result = false;
            break;
        }

        //while------
    }


    cout << result;

    //solve01
    //------
}

/*
如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后，短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。
字母和数字都属于字母数字字符。
给你一个字符串 s，如果它是 回文串 ，返回 true ；否则，返回 false 。
示例 1：
输入: s = "A man, a plan, a canal: Panama"
输出：true
解释："amanaplanacanalpanama" 是回文串。
示例 2：
输入：s = "race a car"
输出：false
解释："raceacar" 不是回文串。
示例 3：
输入：s = " "
输出：true


 */

bool solve02(string s)
{
    string origin_str = s;

    string oh_str;
    for (int i=0; i<origin_str.size(); i++)
    {
        char curr_char = origin_str[i];
        if (curr_char >= 'a' && curr_char<='z')
        {
            oh_str += curr_char;
        }
        else if (curr_char >= 'A' && curr_char<='Z')
        {
            curr_char = curr_char - 'A' + 'a';
            oh_str += curr_char;
        }
        else if (curr_char>='0' && curr_char<='9')
        {
            oh_str += curr_char;
        }
        //for------
    }
    //cout << oh_str;

    if (oh_str.empty()) return true;


    int left = 0;
    int right = oh_str.size() - 1;

    bool result = true;
    while (left<=right)
    {
        if (oh_str[left]==oh_str[right])
        {
            left++;
            right--;
        }
        else
        {
            result = false;
            break;
        }

        //while------
    }

    return result;
    //solve02------
}


/*
返回这两个整数的下标 index1 和 index2
示例 1：

输入：numbers = [2,7,11,15], target = 9
输出：[1,2]
解释：2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。
示例 2：

输入：numbers = [2,3,4], target = 6
输出：[1,3]
解释：2 与 4 之和等于目标数 6 。因此 index1 = 1, index2 = 3 。返回 [1, 3] 。
示例 3：

输入：numbers = [-1,0], target = -1
输出：[1,2]
解释：-1 与 0 之和等于目标数 -1 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。

 */

void solve03(vector<int>&numbers, int target)
{
    vector<int>oh_vec = numbers;
    int left = 0;
    int right = oh_vec.size() - 1;

    vector<int>result_vec(2);

    while (left < right)
    {
        if (oh_vec[left]+oh_vec[right]==target)
        {
            result_vec[0] = left;
            result_vec[1] = right;
            break;
        }
    	else if (oh_vec[left]+oh_vec[right]<target)
        {
            left += 1;
        }
        else if (oh_vec[left] + oh_vec[right] > target)
        {
            right -= 1;
        }
        //while------
    }

    for (auto&item:result_vec)
    {
        cout << item << ' ';
    }

    //solve03------
}



/*
给定一个长度为 n 的整数数组 height 。
有 n 条垂线，第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线，使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。

输入：[1,8,6,2,5,4,8,3,7]
输出：49

 */

void solve04(vector<int>&oh_vec)
{
    int left = 0;
    int right = oh_vec.size() -1;

    int result = 0;
    while (left<right)
    {
        int tmp_result;

        int width = right - left;
        int height = min(oh_vec[left], oh_vec[right]);

        tmp_result = width * height;

        result = max(tmp_result, result);

        if (oh_vec[left] <= oh_vec[right])
        {
            left++;
        }
        else
        {
            right--;
        }
        //while-----
    }
    cout << result;
    //solve04------
}



/*
 三数之和
 给你一个整数数组 nums ，判断是否存在三元组 [nums[i], nums[j], nums[k]]
 满足 i != j、i != k 且 j != k ，
 同时还满足 nums[i] + nums[j] + nums[k] == 0 。
 请你返回所有和为 0 且不重复的三元组。
 输入：nums = [-1,0,1,2,-1,-4]
输出：[[-1,-1,2],[-1,0,1]]
 */

vector<vector<int>> solve05(vector<int>& nums)
{
    vector<int>oh_vec = nums;
    sort(oh_vec.begin(), oh_vec.end());

    vector<vector<int>>result_vec;
    if (nums.size() < 3) return result_vec;
    if (oh_vec[0] > 0) return result_vec;

    if (nums.size()==3)
    {
        int sum = oh_vec[0] + oh_vec[1] + oh_vec[2];
	    if (sum==0)
	    {
            result_vec.push_back(nums);
	    }
        return result_vec;
    }

    for (int i=0; i<oh_vec.size();i++)
    {
        int left = i + 1;
        int right = oh_vec.size() - 1;
        while (left<right)
        {
            int sum = oh_vec[i] + oh_vec[left] + oh_vec[right];

            if (sum > 0)
            {
                right--;
            }
            else if (sum < 0)
            {
                left++;
            }
            else
            {
                vector<int>mini_result = {oh_vec[i], oh_vec[left], oh_vec[right]};
                result_vec.push_back(mini_result);

                while (left<right&& oh_vec[left+1]==oh_vec[left])
                {
                    left += 1;
                }

                while (left<right&&oh_vec[right-1]==oh_vec[right])
                {
                    right -= 1;
                }

                left++;
                right--;
            }


        }

        //for------
    }
    return result_vec;
    //solve05------
}



int main()
{

	{
        //-1,0,1,2,-1,-4
        vector<int>nums = { -2,0,1,1,2 };
        vector<vector<int>>result_vec = solve05(nums);

        cout << result_vec.size() << endl;

        //for (auto&item:result_vec[0])
        //{
        //    cout << item << ' ';
        //}

        return 0;
	}

	{
        vector<int>oh_vec = { 1,8,6,2,5,4,8,3,7 };
        solve04(oh_vec);
        return 0;
	}


	{
        vector<int>numbers = { 2, 3, 4 };
        int target = 6;
        solve03(numbers, target);
        return 0;
	}

	{
        string s = "0P";
        cout << solve02(s);
        return 0;
	}


    solve01(121);
}

// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门使用技巧: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件，或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来，若要再次打开此项目，请转到“文件”>“打开”>“项目”并选择 .sln 文件
